fix(claude-ops): resolve built-in descriptions the inventory left unresolved - #5619
Conversation
…esolved The inventory now follows a call with arguments into its function with the parameters shadowed, resolves template substitutions, || and ?? fallbacks, parenthesized parts and joined arrays, and resolves identifiers by module (import to the exporting module, else the module itself). On Claude Code 2.1.285 unresolved descriptions drop from 14 to 1 (design). Detect scores PascalCase native names as words and scores the user-facing name, and native_drift files an unresolved-description item for each name the previous summary did not list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…-tool-descriptions # Conflicts: # plugins/claude-ops/.claude-plugin/plugin.json # plugins/claude-ops/CHANGELOG.md
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Claude finished @kyle-sexton's task in 44s —— View job Security review — PR #5619
No security issues found. Reviewed all 10 changed files (
None of the changed files are |
|
Claude finished @kyle-sexton's task in 6m 36s —— View job Code review complete
SummaryReviewed the diff against One finding posted inline, worth the author's attention but not necessarily blocking:
There is test coverage for "an old-shape previous summary (missing the field) files every name once" via a non- Everything else reviewed (module-scoped resolution rules, PascalCase splitting, |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 337bf9182a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Keep single-letter bindings inside their module, take a later module binding only from inside a function body, prefer a resolved left operand over its || or ?? fallback, and record the 2.1.285 bundle claims as verification records. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Claude finished @kyle-sexton's task in 1m 21s —— View job Security review — PR #5619
No security issues found. Reviewed all 10 changed files (diff scoped to
None of the changed files are |
|
Claude finished @kyle-sexton's task in 5m 5s —— View job Code review complete
SummaryReviewed All four prior Codex findings are fixed, each with a new regression test:
One new finding on the fix itself, posted inline on Not re-raised: the earlier open question about Verification claims in the PR body (test counts, before/after unresolved-description counts, timing) are author-reported and not independently re-run here — this lane has no execution access. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b32c7081bf
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…strings A binding after the reader is taken only when the read is reached through a getter, method, arrow or function-valued field and the binding is top-level, so an eager call at load time stays unresolved. `??` keeps any string left operand, including "". Document and test why a baseline drift run files every unresolved description. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Claude finished @kyle-sexton's task in 1m 29s —— View job Security review — PR #5619
No security issues found. Reviewed the full diff (
This confirms the two prior security-review passes on this PR (head |
|
Claude finished @kyle-sexton's task in 3m 27s —— View job Code review complete
SummaryReviewed Both are fixed correctly, each with a regression test:
Also in this commit: No new findings. I did not find additional correctness issues in this commit's diff. Static trace only — this lane has no code-execution access, so |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b4450688b3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…iant A plain parameter takes the values its call-site argument resolves to, a concatenation keeps every combination of its parts' values (capped at 16), and a fallback keeps the left operand's non-empty variants; a call or group on the left never settles a fallback, since it can yield a non-string. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b3be945bbd
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…-tool-descriptions # Conflicts: # plugins/claude-ops/.claude-plugin/plugin.json # plugins/claude-ops/CHANGELOG.md
|
Claude finished @kyle-sexton's task in 2m 45s —— View job Code review complete
SummaryScoped to the 10 changed files ( The one gap: three P2 findings Codex posted against
None of these are newly introduced by the merge commit — they're latent in logic added by |
|
Claude finished @kyle-sexton's task in 57s —— View job Security review — PR #5619
No security issues found. Reviewed all 10 changed files (
This confirms the four prior security-review passes already posted on this PR across earlier commits, which also found no issues; this pass covers the full current head ( |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1cbce94b40
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… heads - A declaration with no initializer (`let x;`, `var x` after the read) or a `catch (x)` parameter between a binding and its read leaves the read unresolved, for long and one-letter names; an imported binding is checked against the reader's own module only. - A nested function head is matched with quoted text blanked, so a default such as `sep=")"` is recognized; an unreadable head raises, which leaves the value unresolved. - A parameter followed in its statement by `]=` or `}=` counts as written, so nested destructuring unbinds it. No description on Claude Code 2.1.285 changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Claude finished @kyle-sexton's task in 1m 4s —— View job Security review — PR #5619
No security issues found. This PR has been through many clean security-review passes on prior heads ( The only commit in that window is
No other files changed in this window. The PR's full changed-file set (10 files) remains confined to Branch · |
|
Claude finished @kyle-sexton's task in 6m 17s —— View job Code review complete
SummaryThe only commit since the last reviewed head (
Re-verified the previously open finding (my own comment on the Two non-blocking precision notes, both fail-safe (can only turn a real value into
Not independently re-run: this lane has no code-execution access ( No new findings. Every finding raised across this PR's ~55+ review rounds has been fixed with regression tests and independently re-verified, and this round's commit closes the three remaining open items with no new issue found. Branch · |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 121806dd6e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…eads
- A `let` or `const` in a `for (...)` head is visible only in that loop;
an unbraced loop body raises, leaving the value unresolved.
- Method and function parameter lists are matched with quoted text
blanked (`_head_open`), so `a="("` no longer drops a parameter from
the shadow scope.
- A function declaration whose parameter list holds parentheses leaves
calls to that name in its module unresolved instead of falling back
to another declaration.
No description on Claude Code 2.1.285 changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Claude finished @kyle-sexton's task in 5m 16s —— View job Code review complete
SummaryThe only functional commit since the last reviewed head (
One finding, posted inline on Not independently re-run: Not re-raised: everything else fixed across this PR's ~55 review rounds (module-boundary resolution and visibility, deferred-read tracking, Branch · |
|
Claude finished @kyle-sexton's task in 1m 27s —— View job Security review complete
No security issues found. This PR has been through many clean security-review passes on prior heads ( Two commits landed in that window:
Full diff against the merge-base with Branch · |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e4b2d08a9d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…eads
- A `catch (x)` block is scanned with its parameters added to the
shadow scope, so a followed function's bound `x` does not leak in.
- `_function_block` finds a control head's `(` with quoted text
blanked, so `if(a==="(")` is not taken for a function body.
No description on Claude Code 2.1.285 changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
@codex review |
|
Claude finished @kyle-sexton's task in 1m 40s —— View job Security review — PR #5619
No security issues found. This PR has been through many clean security-review passes on prior heads ( Two commits landed in that window:
No other files changed in this window. Confirmed the full PR diff ( Branch · |
|
Claude finished @kyle-sexton's task in 3m 28s —— View job Code review complete
SummaryTwo commits landed since the last reviewed head (
I additionally traced two correctness properties by hand (no execution access in this sandbox, consistent with every prior round on this PR):
No new findings. Both new regression tests use |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9be6b2a186
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ed (#5648) No related issue: follow-up to #5619, whose inventory fix exposed new and changed native descriptions on Claude Code 2.1.285. ## Summary After #5619, `overlap.py detect` on the 2.1.285 extraction listed 17 unruled pairs plus 12 dismissals that resurfaced because their native description text changed. This PR rules all 29: 12 re-dismissed, 14 dismissed, 3 route rows, 0 defer. Detect now reports 0 unruled and 0 resurfaced. | Native (class) | Component | Ruling | Reason | |---|---|---|---| | `EnterWorktree` (builtin-tool) | source-control:worktree | route row, complementary | Ours creates at an external root (never by name) and enters existing worktrees only after its claim check, both ending in `EnterWorktree(path:)` | | `ExitWorktree` (builtin-tool) | source-control:worktree | route row, complementary | Tool leaves a worktree session; ours removes worktrees (`cleanup`) | | `ProposeGoal` (builtin-tool) | planning:draft-goal-condition | route row, complementary | Ours drafts the condition and always emits the `/goal` line; it also proposes through the tool (ask_user true) in an interactive main-thread session outside plan mode, within the tool cap | | `ClaudeDesign` (builtin-tool) | planning:design-handoff | dismissed | Design canvas projects vs. software design gate; shared word | | `ClaudeDesign` | planning:design | dismissed | Canvas projects vs. types/contracts design; shared word | | `ClaudeDesign` | evals:design | dismissed | Canvas projects vs. eval suite design; shared word | | `DesignSync` (builtin-tool) | dometrain:sync | dismissed | Design-system sync vs. vendored-content drift check; shared word | | `DesignSync` | repo-fleet-hygiene:sync | dismissed | Design-system sync vs. fleet checkout sync; shared word | | `ProposeGoal` | performance:goal | dismissed | Session goal vs. performance target; shared word | | `ReadNotifications` (builtin-tool) | desktop-notification:setup | dismissed | Queued webhook notifications vs. notification hook setup; shared word | | `ReportFindings` (builtin-tool) | improvement:find | dismissed | Renders code-review findings in the host UI vs. ranks improvements; shared words | | `TestingPermission` (builtin-tool) | claude-config:audit-permission-grants | dismissed | Internal test tool that always asks permission; shared word | | `TestingPermission` | claude-config:audit-permission-state | dismissed | Same | | `TestingPermission` | testing:test-value | dismissed | Same | | `TodoWrite` (builtin-tool) | work-items:scan-todos | dismissed | Session checklist vs. TODO comment sweep; shared word | | `WaitForMcpServers` (builtin-tool) | discipline:wait-what | dismissed | MCP connection wait vs. re-pitching a message; shared word | | `config` (builtin-command) | claude-config:audit-permission-grants | dismissed | Settings UI vs. permission-grant audit; shared word | | `Bash` (builtin-tool) | bash-format:setup | re-dismissed | Original reason holds: runs commands vs. formatter hook setup | | `Bash` | bash-format:check | re-dismissed | Original reason holds: runs commands vs. binary check | | `PowerShell` (builtin-tool) | powershell-format:setup | re-dismissed | Original reason holds | | `PowerShell` | powershell-format:check | re-dismissed | Original reason holds | | `Workflow` (builtin-tool) | session-flow:workflow | re-dismissed | Resolved text is the Workflow script reference; still a shared word | | `Workflow` | songwriting:workflow | re-dismissed | Same | | `code-review` (bundled-skill) | review:security-review | re-dismissed | Still correctness review vs. CI security lane; security pair recorded separately | | `config` | claude-config:audit | re-dismissed | Now "Open settings"; still preferences UI vs. settings audit | | `config` | claude-config:audit-permission-state | re-dismissed | Same | | `memory_read` (builtin-tool) | claude-memory:audit | re-dismissed | Session memory store vs. CLAUDE.md/rules audit | | `workflow-authoring` (bundled-skill) | playbooks:skill-authoring | re-dismissed | Workflow scripts vs. SKILL.md authoring | | `workflow-authoring` | songwriting:workflow | re-dismissed | Workflow scripts vs. songwriting router | ## Fix - `docs/native-surfaces/records.json`: 3 rows and 26 dismissal records; `docs/native-surfaces.md` regenerated. - `source-control:worktree`: description phrase (source-control's route rows carry phrases), `## Boundary` naming `EnterWorktree` and `ExitWorktree`, `reference/native-worktree.md`. Version 0.69.0. - `planning:draft-goal-condition`: Boundary extended to `ProposeGoal`, Step 4 pointer, records in `reference/native-goal.md`. No description phrase, matching planning's other route row. Version 0.56.0. - `ProposeGoal`'s `ask_user`, 500-character cap, and session restrictions were read from the 2.1.285 binary's tool prompt; the tool is not on the tools reference. ## Verification - `overlap.py detect --inventory <2.1.285 json> --repo .`: 0 unruled, 0 resurfaced. - `overlap.py generate --check`: in sync (69 rows, 93 dismissals). `overlap.py self-check`: degraded with the 2 advisories main already carries (recorded versions older than 2.1.286, upstream SHA not checked), no failures. - `node scripts/generate-catalog.mjs`: no change. `check-skill.sh` PASS for `worktree` and `draft-goal-condition`. markdownlint clean. ## Related - #5619 (inventory fix that surfaced these) - #5640 (parser follow-up) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
…outer names in the inventory (#5649) Refs: #5640 ## Summary The inventory extractor resolved a name through an import or an outer binding even when the reader's own scope declared or bound the same name, so a built-in description could read a foreign value. ## Fix - A name the module imports but an enclosing block of the reader declares now resolves as a runtime value, not through the import. - A `let`/`const` in a `for (...)` head (including `for await`) shadows outer names in the loop body. - Regression tests cover both; claude-ops bumps to 0.78.1 with a changelog entry, and `extraction.md` lists the scoping rules. The title's full parser replacement stays the owner's call, so this does not close the issue. ## Verification `python3 -m unittest test_inventory` in `plugins/claude-ops/skills/inventory/scripts`: 196 tests OK. `plugin.json` parses. ## Related Refs #5640; follows #5619. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… a non-constant expression (#5704) Closes #5700 Closes #5701 ## Summary On Claude Code 2.1.286 the inventory reported a built-in command `string` that does not exist. The generic skill loader builds `{type:"prompt",name:Vt,...}` with `Vt=$t?smt(e):e` in its own scope. The name resolver searched an index that holds only string bindings, so it could not see that nearer conditional binding and picked an unrelated `Vt="string"` megabytes earlier. That is a wrong value. The reader is supposed to fail closed: a name it cannot resolve stays unresolved. ## Fix - Before a name candidate is accepted, `_scoped_constant` checks it with the module and scope rule that field resolution uses (`_binding_value`). The candidate must be the string constant that this read sees. A name bound to a conditional, a call or any other non-constant expression stays unresolved, and so does a name whose constant lives in another module. The check applies to commands, bundled skills, subagents and tools: `resolve_name_ident` and `resolve_tool_ident` now take `src` and `braces`. - `_binding_value` gains a `window` argument, so a single-character name keeps the existing `SHORT_IDENT_LOCALITY_BYTES` reach. - `VALIDATED_AGAINST` is now `2.1.286`. claude-ops is bumped to 0.79.2 with a CHANGELOG entry, and `reference/extraction.md` describes the check. ## Verification - Full `--binary-only` inventories were diffed before (origin/main) and after the fix: - 2.1.285: no surface changes. Only the `validated_against` advisory text differs. - 2.1.286: `builtin_commands.string` is removed and `string` drops out of `integrity.undetermined`. Nothing else changed in any lane. No other phantom of this bug class turned up. - 2.1.285 to 2.1.286 after the fix: every lane has the same names. The field changes are `pause-memory` (its description is now a getter), `plugin-types` (now hidden) and Explore/Plan `disallowed_tools`. The Explore/Plan lists are `partial` because the `...pY` spread hits a nearer `pY=p(...)` call. That is fail-closed (the list is a floor), and this PR leaves it alone. - `inventory.py --self-check` on the installed CLI: `OK: cli 2.1.286, validated against 2.1.286`, all six lanes `ok`. Eval-backed facts hold on 2.1.286: `usage` aliases `cost`/`stats`, `heapdump`/`sandbox` hidden, `teleport` hidden and gated, `vim` `removed_in_docs`. - `test_inventory.py`: 209 OK. New fixtures cover a name shadowed by a conditional (the 2.1.286 shape), by a call, by a non-constant in a bundled skill and in a tool, a constant in another module, and a same-scope snake_case rebinding of a tool. Positive controls cover an in-scope constant and an imported one. With the guard stubbed out, 6 of the new tests fail. - `test_overlap.py` 184 OK, `overlap.test.sh` passes, `test_native_drift.py` 40 OK, `native_drift.test.sh` passes, and `scripts/run-ruff.sh check` and `format --check` are clean. ## Related - #5640 (inventory wrong-value findings) - #5619 (module and scope resolution for descriptions, reused here) 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
… in its own scope (#5717) Closes #5711 ## Summary On Claude Code 2.1.286 the inventory read the built-in Explore and Plan agents' `disallowedTools` as `partial`. Both definitions spread a shared list (`...pY`). The spread resolver took the nearest `pY=` binding anywhere in the bundle, which on 2.1.286 is an unrelated `pY=p(...)` call, so the shared entries, the Artifact tools among them, were dropped. ## Fix - `_array_names` resolves a `...spread` element through a new `_spread_array` helper. It reads the binding with `_binding_value` at the spread's own offset, the same module and scope rule `_scoped_constant` applies to names and fields (#5619, #5704). Before, it used `_nearest_binding`. - Fail-closed: - When the scoped binding is not an array literal (a call, a conditional, or undeterminable), the list stays `partial`. - When the selected binding is a bare or conditional assignment rather than a declaration (`if(c)pY=["B"]`, `pY=c?["B"]:pY`, `c&&(pY=["B"])`, an unbraced `for(...)pY=["B"]`), or any other write in the same block reaches it, the list stays `partial`. A `var` reached back through a chain of simple declarators counts as a declaration, which keeps Explore and Plan resolving: their `pY` follows a function declaration that has no `;`, and `_declares` misses that statement. - When code off the declaring block's straight line assigns the binding without declaring its own, the list also stays `partial`. That code is a nested block (`if(c){pY=["B"]}`, a loop body), another function (`function init(){pY=["B"]}`), or an expression-bodied arrow (`var f=()=>pY=["B"]`, in either order relative to the declaration). A read can then see B, so the list is not static. This check (`_written_elsewhere`) applies only to the spread path. Applied inside `_binding_value`, it changed many unrelated description fields on both 2.1.285 and 2.1.286 and made the run about 5x slower, so it is not shared with name and field resolution. - Tests in `test_inventory.py`: - A spread whose nearest same-name binding is local to another function resolves to the in-scope array. This test fails on the unfixed resolver. - A spread whose in-scope binding is a conditional stays `partial`. - A spread whose binding another function, a nested `if` or loop block, or an expression-bodied arrow reassigns stays `partial`. - A writer that declares its own local of the same name does not block resolution. - `reference/extraction.md` states the spread rule. claude-ops 0.79.2 -> 0.79.3, with a CHANGELOG entry. ## Verification - `inventory.py --binary-only` on 2.1.286, diffed against the prior run (`.work/cc-2.1.286/inv-final.json`). Only these fields changed: - `builtin_agents/Explore/disallowed_tools`: `[Agent, ExitPlanMode, Edit, Write, NotebookEdit]` -> `[Agent, Artifact, ArtifactComments, ArtifactData, ArtifactCheck, ExitPlanMode, Edit, Write, NotebookEdit]` - `builtin_agents/Explore/disallowed_tools_source`: `partial` -> `literal` - `builtin_agents/Plan/disallowed_tools` and `disallowed_tools_source`: the same change - On 2.1.285, the inventory output is identical to origin/main's. - The reassignment checks (commits f88d9bf and 117a3fb) left the 2.1.285 and 2.1.286 outputs identical to the first fix commit (3075883), and runtime is unchanged (about 22s). - `inventory.py --self-check`: `OK: cli 2.1.286, validated against 2.1.286`, with all six lanes ok. - `python3 -m unittest test_inventory`: `Ran 215 tests ... OK`. - `overlap.py detect`: exit 0, with `discovered: 0` and `resurfaced: 0`. `overlap.py generate --check` reports the docs are in sync. `node scripts/generate-catalog.mjs` produced no diff. - `scripts/run-ruff.sh check` and `format --check` pass on both files. ## Related - #5640: move to a real JavaScript parser, which would replace these scope heuristics. - #5704 / #5700: the same scoped-binding rule, applied to names. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
No related issue: operator-directed fix from the 2.1.284/2.1.285 native-surface review (ClaudeDesign had an empty description, so detect never paired it).
Summary
inventory.pyleft 14 built-in descriptions unresolved on Claude Code 2.1.285 (13 tools plus thedesignbundled skill). It now resolves 13 of them.designstays unresolved because its text reads a table keyed by a runtime mode. Detect also scores native names that have no description, and native drift now files each newly unresolved description.Fix
inventory.py). A call with arguments (kbr(RTe()),gLr(void 0),P({...})) is now followed into its function, with that function's parameters shadowed. Template substitutions resolve, and so do||/??fallbacks (an empty""fallback is skipped), parenthesized parts such asd+(x()?m:c)+p, and[...].join(sep)arrays. A template made only of runtime parts stays unresolved.workflow-authoring's${jd}readsWorkflow, not another module's localhost_exit. A single-letter function resolves only when it is the one top-level declaration in its module.discover.py). PascalCase native names are split into words (ClaudeDesignscores as "design",EnterWorktreeas "enter worktree").user_facing_nameis scored. It is not added to the dismissal fingerprint, soaudit-native-overlap/SKILL.mdstays accurate.native_drift.py).summarizerecordsintegrity.undetermined.description_unresolved.diffadds anunresolved-descriptionitem (keynative-drift:unresolved-description:<name>:inventory) for each name the previous summary did not list. These items go through the existing key-based filing path, with no label.context/native-drift.mddocuments the new kind and its title.claude-ops0.75.1 -> 0.76.0, with a CHANGELOG entry.docs/native-surfaces/records.jsonand all skill bodies are unchanged.Verification
test_inventory.py: 144 tests OK (10 new synthetic-bundle cases, negative cases included).test_overlap.py: 182 OK.test_native_drift.py: 40 OK.overlap.test.shandnative_drift.test.shexit 0. The pinnedscripts/run-ruff.sh check/format,markdownlint-cli2andtyposall pass.inventory.py --self-checkon the installed 2.1.285 exits 3 with only the version advisory, the same result asorigin/main. All lanes are ok. The run takes about 12 s (11 s before).ALWAYS use Grep ... as a Bash command,workflow-authoringWorkflow, and Edit user-facing nameUpdate.overlap.py detect --inventory <2.1.285> --repo .goes from 23 to 50 candidates. The operator rules on the new candidates and on the dismissals that came back because their descriptions changed.Related
🤖 Generated with Claude Code